bitkeeper revision 1.1159.256.1 (420919a4fFt2x7Ej4o_xqAI2CSYN8Q)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Tue, 8 Feb 2005 19:57:24 +0000 (19:57 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Tue, 8 Feb 2005 19:57:24 +0000 (19:57 +0000)
mmu_update fixes for x86_64. About halfway there.
Signed-off-by: keir.fraser@cl.cam.ac.uk
xen/arch/x86/boot/x86_64.S
xen/arch/x86/mm.c
xen/include/asm-x86/cpufeature.h
xen/include/asm-x86/page.h
xen/include/asm-x86/x86_32/page.h
xen/include/asm-x86/x86_64/page.h

index 9d615231384b7f80db1e0ad3ec1899c58f4f8529..2b89d9caa42dcfb6ba54b0b8eb6ee47fb4519785 100644 (file)
@@ -75,6 +75,7 @@ __start:
         cpuid
         bt      $29,%edx            # Long mode feature?
         jnc     bad_cpu
+        mov     %edx,%edi
 skip_boot_checks:
 
         /* Set up FPU. */
@@ -91,9 +92,12 @@ skip_boot_checks:
         /* Set up EFER (Extended Feature Enable Register). */
         movl    $MSR_EFER, %ecx
         rdmsr
-        /* Long Mode, SYSCALL/SYSRET, No-Execute */
-        movl    $(EFER_LME|EFER_SCE|EFER_NX),%eax
-        wrmsr
+        btsl    $_EFER_LME,%eax /* Long Mode      */
+        btsl    $_EFER_SCE,%eax /* SYSCALL/SYSRET */
+        btl     $20,%edi        /* CPUID 0x80000001, EDX[20] */
+        jnc     1f
+        btsl    $_EFER_NX,%eax  /* No-Execute     */
+1:      wrmsr
 
         mov     $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */
         mov     %eax,%cr0
index 1c030ffd1a2dffde1e65b83b835b37b34b53f0d8..6ae4d0e95c537c3a4e7f6901c5169cc8f063d963 100644 (file)
@@ -335,47 +335,48 @@ static int get_page_and_type_from_pagenr(unsigned long page_nr,
 
 
 /*
- * We allow an L2 tables to map each other (a.k.a. linear page tables). It
- * needs some special care with reference counst and access permissions:
+ * We allow root tables to map each other (a.k.a. linear page tables). It
+ * needs some special care with reference counts and access permissions:
  *  1. The mapping entry must be read-only, or the guest may get write access
  *     to its own PTEs.
  *  2. We must only bump the reference counts for an *already validated*
  *     L2 table, or we can end up in a deadlock in get_page_type() by waiting
  *     on a validation that is required to complete that validation.
  *  3. We only need to increment the reference counts for the mapped page
- *     frame if it is mapped by a different L2 table. This is sufficient and
- *     also necessary to allow validation of an L2 table mapping itself.
+ *     frame if it is mapped by a different root table. This is sufficient and
+ *     also necessary to allow validation of a root table mapping itself.
  */
 static int 
 get_linear_pagetable(
-    l2_pgentry_t l2e, unsigned long pfn, struct domain *d)
+    root_pgentry_t re, unsigned long re_pfn, struct domain *d)
 {
     u32 x, y;
     struct pfn_info *page;
+    unsigned long pfn;
 
-    if ( (l2_pgentry_val(l2e) & _PAGE_RW) )
+    if ( (root_pgentry_val(re) & _PAGE_RW) )
     {
         MEM_LOG("Attempt to create linear p.t. with write perms");
         return 0;
     }
 
-    if ( (l2_pgentry_val(l2e) >> PAGE_SHIFT) != pfn )
+    if ( (pfn = root_pgentry_to_pfn(re)) != re_pfn )
     {
         /* Make sure the mapped frame belongs to the correct domain. */
-        if ( unlikely(!get_page_from_pagenr(l2_pgentry_to_pfn(l2e), d)) )
+        if ( unlikely(!get_page_from_pagenr(pfn, d)) )
             return 0;
 
         /*
          * Make sure that the mapped frame is an already-validated L2 table. 
          * If so, atomically increment the count (checking for overflow).
          */
-        page = &frame_table[l2_pgentry_to_pfn(l2e)];
+        page = &frame_table[pfn];
         y = page->u.inuse.type_info;
         do {
             x = y;
             if ( unlikely((x & PGT_count_mask) == PGT_count_mask) ||
                  unlikely((x & (PGT_type_mask|PGT_validated)) != 
-                          (PGT_l2_page_table|PGT_validated)) )
+                          (PGT_root_page_table|PGT_validated)) )
             {
                 put_page(page);
                 return 0;
@@ -400,9 +401,9 @@ get_page_from_l1e(
     if ( !(l1v & _PAGE_PRESENT) )
         return 1;
 
-    if ( unlikely(l1v & (_PAGE_GLOBAL|_PAGE_PAT)) )
+    if ( unlikely(l1v & L1_DISALLOW_MASK) )
     {
-        MEM_LOG("Bad L1 type settings %04lx", l1v & (_PAGE_GLOBAL|_PAGE_PAT));
+        MEM_LOG("Bad L1 type settings %04lx", l1v & L1_DISALLOW_MASK);
         return 0;
     }
 
@@ -439,10 +440,10 @@ get_page_from_l2e(
     if ( !(l2_pgentry_val(l2e) & _PAGE_PRESENT) )
         return 1;
 
-    if ( unlikely((l2_pgentry_val(l2e) & (_PAGE_GLOBAL|_PAGE_PSE))) )
+    if ( unlikely((l2_pgentry_val(l2e) & L2_DISALLOW_MASK)) )
     {
         MEM_LOG("Bad L2 page type settings %04lx",
-                l2_pgentry_val(l2e) & (_PAGE_GLOBAL|_PAGE_PSE));
+                l2_pgentry_val(l2e) & L2_DISALLOW_MASK);
         return 0;
     }
 
@@ -450,12 +451,62 @@ get_page_from_l2e(
         l2_pgentry_to_pfn(l2e), 
         PGT_l1_page_table | (va_idx<<PGT_va_shift), d);
 
+#if defined(__i386__)
+    return rc ? rc : get_linear_pagetable(l2e, pfn, d);
+#elif defined(__x86_64__)
+    return rc;
+#endif
+}
+
+
+#ifdef __x86_64__
+
+static int 
+get_page_from_l3e(
+    l3_pgentry_t l3e, unsigned long pfn, struct domain *d)
+{
+    if ( !(l3_pgentry_val(l3e) & _PAGE_PRESENT) )
+        return 1;
+
+    if ( unlikely((l3_pgentry_val(l3e) & L3_DISALLOW_MASK)) )
+    {
+        MEM_LOG("Bad L3 page type settings %04lx",
+                l3_pgentry_val(l3e) & L3_DISALLOW_MASK);
+        return 0;
+    }
+
+    return get_page_and_type_from_pagenr(
+        l3_pgentry_to_pfn(l3e), PGT_l3_page_table, d);
+}
+
+
+static int 
+get_page_from_l4e(
+    l4_pgentry_t l4e, unsigned long pfn, struct domain *d)
+{
+    int rc;
+
+    if ( !(l4_pgentry_val(l4e) & _PAGE_PRESENT) )
+        return 1;
+
+    if ( unlikely((l4_pgentry_val(l4e) & L4_DISALLOW_MASK)) )
+    {
+        MEM_LOG("Bad L4 page type settings %04lx",
+                l4_pgentry_val(l4e) & L4_DISALLOW_MASK);
+        return 0;
+    }
+
+    rc = get_page_and_type_from_pagenr(
+        l4_pgentry_to_pfn(l4e), PGT_l4_page_table, d);
+
     if ( unlikely(!rc) )
-        return get_linear_pagetable(l2e, pfn, d);
+        return get_linear_pagetable(l4e, pfn, d);
 
     return 1;
 }
 
+#endif /* __x86_64__ */
+
 
 static void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
 {
@@ -514,17 +565,62 @@ static void put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn)
 }
 
 
+#ifdef __x86_64__
+
+static void put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn)
+{
+    if ( (l3_pgentry_val(l3e) & _PAGE_PRESENT) && 
+         ((l3_pgentry_val(l3e) >> PAGE_SHIFT) != pfn) )
+        put_page_and_type(&frame_table[l3_pgentry_to_pfn(l3e)]);
+}
+
+
+static void put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn)
+{
+    if ( (l4_pgentry_val(l4e) & _PAGE_PRESENT) && 
+         ((l4_pgentry_val(l4e) >> PAGE_SHIFT) != pfn) )
+        put_page_and_type(&frame_table[l4_pgentry_to_pfn(l4e)]);
+}
+
+#endif /* __x86_64__ */
+
+
+static int alloc_l1_table(struct pfn_info *page)
+{
+    struct domain *d = page_get_owner(page);
+    unsigned long  pfn = page_to_pfn(page);
+    l1_pgentry_t  *pl1e;
+    int            i;
+
+    pl1e = map_domain_mem(pfn << PAGE_SHIFT);
+
+    for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
+        if ( unlikely(!get_page_from_l1e(pl1e[i], d)) )
+            goto fail;
+
+    unmap_domain_mem(pl1e);
+    return 1;
+
+ fail:
+    while ( i-- > 0 )
+        put_page_from_l1e(pl1e[i], d);
+
+    unmap_domain_mem(pl1e);
+    return 0;
+}
+
+
 static int alloc_l2_table(struct pfn_info *page)
 {
     struct domain *d = page_get_owner(page);
-    unsigned long  page_nr = page_to_pfn(page);
+    unsigned long  pfn = page_to_pfn(page);
     l2_pgentry_t  *pl2e;
     int            i;
    
-    pl2e = map_domain_mem(page_nr << PAGE_SHIFT);
+    pl2e = map_domain_mem(pfn << PAGE_SHIFT);
 
     for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
-        if ( unlikely(!get_page_from_l2e(pl2e[i], page_nr, d, i)) )
+        if ( unlikely(!get_page_from_l2e(pl2e[i], pfn, d, i)) )
             goto fail;
 
 #if defined(__i386__)
@@ -533,7 +629,7 @@ static int alloc_l2_table(struct pfn_info *page)
            &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
            HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
     pl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
-        mk_l2_pgentry((page_nr << PAGE_SHIFT) | __PAGE_HYPERVISOR);
+        mk_l2_pgentry((pfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
     pl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
         mk_l2_pgentry(__pa(page_get_owner(page)->arch.mm_perdomain_pt) | 
                       __PAGE_HYPERVISOR);
@@ -544,61 +640,67 @@ static int alloc_l2_table(struct pfn_info *page)
 
  fail:
     while ( i-- > 0 )
-        put_page_from_l2e(pl2e[i], page_nr);
+        put_page_from_l2e(pl2e[i], pfn);
 
     unmap_domain_mem(pl2e);
     return 0;
 }
 
 
-static int alloc_l1_table(struct pfn_info *page)
+#ifdef __x86_64__
+
+static int alloc_l3_table(struct pfn_info *page)
 {
     struct domain *d = page_get_owner(page);
-    unsigned long  page_nr = page_to_pfn(page);
-    l1_pgentry_t  *pl1e;
+    unsigned long  pfn = page_to_pfn(page);
+    l3_pgentry_t  *pl3e = page_to_virt(page);
     int            i;
 
-    pl1e = map_domain_mem(page_nr << PAGE_SHIFT);
-
-    for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
-        if ( unlikely(!get_page_from_l1e(pl1e[i], d)) )
+    for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )
+        if ( unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) )
             goto fail;
 
-    unmap_domain_mem(pl1e);
     return 1;
 
  fail:
     while ( i-- > 0 )
-        put_page_from_l1e(pl1e[i], d);
+        put_page_from_l3e(pl3e[i], pfn);
 
-    unmap_domain_mem(pl1e);
     return 0;
 }
 
 
-static void free_l2_table(struct pfn_info *page)
+static int alloc_l4_table(struct pfn_info *page)
 {
-    unsigned long page_nr = page - frame_table;
-    l2_pgentry_t *pl2e;
-    int i;
+    struct domain *d = page_get_owner(page);
+    unsigned long  pfn = page_to_pfn(page);
+    l4_pgentry_t  *pl4e = page_to_virt(page);
+    int            i;
 
-    pl2e = map_domain_mem(page_nr << PAGE_SHIFT);
+    for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ )
+        if ( unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) )
+            goto fail;
 
-    for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
-        put_page_from_l2e(pl2e[i], page_nr);
+    return 1;
 
-    unmap_domain_mem(pl2e);
+ fail:
+    while ( i-- > 0 )
+        put_page_from_l4e(pl4e[i], pfn);
+
+    return 0;
 }
 
+#endif /* __x86_64__ */
+
 
 static void free_l1_table(struct pfn_info *page)
 {
     struct domain *d = page_get_owner(page);
-    unsigned long page_nr = page - frame_table;
+    unsigned long pfn = page_to_pfn(page);
     l1_pgentry_t *pl1e;
     int i;
 
-    pl1e = map_domain_mem(page_nr << PAGE_SHIFT);
+    pl1e = map_domain_mem(pfn << PAGE_SHIFT);
 
     for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
         put_page_from_l1e(pl1e[i], d);
@@ -607,6 +709,47 @@ static void free_l1_table(struct pfn_info *page)
 }
 
 
+static void free_l2_table(struct pfn_info *page)
+{
+    unsigned long pfn = page_to_pfn(page);
+    l2_pgentry_t *pl2e;
+    int i;
+
+    pl2e = map_domain_mem(pfn << PAGE_SHIFT);
+
+    for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
+        put_page_from_l2e(pl2e[i], pfn);
+
+    unmap_domain_mem(pl2e);
+}
+
+
+#ifdef __x86_64__
+
+static void free_l3_table(struct pfn_info *page)
+{
+    unsigned long pfn = page_to_pfn(page);
+    l3_pgentry_t *pl3e = page_to_virt(page);
+    int           i;
+
+    for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )
+        put_page_from_l3e(pl3e[i], pfn);
+}
+
+
+static void free_l4_table(struct pfn_info *page)
+{
+    unsigned long pfn = page_to_pfn(page);
+    l4_pgentry_t *pl4e = page_to_virt(page);
+    int           i;
+
+    for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ )
+        put_page_from_l4e(pl4e[i], pfn);
+}
+
+#endif /* __x86_64__ */
+
+
 static inline int update_l2e(l2_pgentry_t *pl2e, 
                              l2_pgentry_t  ol2e, 
                              l2_pgentry_t  nl2e)
@@ -738,6 +881,12 @@ int alloc_page_type(struct pfn_info *page, unsigned int type)
         return alloc_l1_table(page);
     case PGT_l2_page_table:
         return alloc_l2_table(page);
+#ifdef __x86_64__
+    case PGT_l3_page_table:
+        return alloc_l3_table(page);
+    case PGT_l4_page_table:
+        return alloc_l4_table(page);
+#endif
     case PGT_gdt_page:
     case PGT_ldt_page:
         return alloc_segdesc_page(page);
@@ -766,6 +915,16 @@ void free_page_type(struct pfn_info *page, unsigned int type)
         free_l2_table(page);
         break;
 
+#ifdef __x86_64__
+    case PGT_l3_page_table:
+        free_l3_table(page);
+        break;
+
+    case PGT_l4_page_table:
+        free_l4_table(page);
+        break;
+#endif
+
     default:
         BUG();
     }
@@ -856,7 +1015,8 @@ int get_page_type(struct pfn_info *page, u32 type)
                  * circumstances should be very rare.
                  */
                 struct domain *d = page_get_owner(page);
-                if ( unlikely(NEED_FLUSH(tlbflush_time[d->exec_domain[0]->processor],
+                if ( unlikely(NEED_FLUSH(tlbflush_time[d->exec_domain[0]->
+                                                      processor],
                                          page->tlbflush_timestamp)) )
                 {
                     perfc_incr(need_flush_tlb_flush);
index 117ca6a9d748c8caf1c6b780d0bf78731c6ae0e7..58aae2a74e10097040a45ede45622c27fb2d569c 100644 (file)
@@ -48,6 +48,7 @@
 /* Don't duplicate feature flags which are redundant with Intel! */
 #define X86_FEATURE_SYSCALL    (1*32+11) /* SYSCALL/SYSRET */
 #define X86_FEATURE_MP         (1*32+19) /* MP Capable. */
+#define X86_FEATURE_NX         (1*32+20) /* No-Execute Bit. */
 #define X86_FEATURE_MMXEXT     (1*32+22) /* AMD MMX extensions */
 #define X86_FEATURE_LM         (1*32+29) /* Long Mode (x86-64) */
 #define X86_FEATURE_3DNOWEXT   (1*32+30) /* AMD 3DNow! extensions */
@@ -98,6 +99,7 @@
 #define cpu_has_xmm            boot_cpu_has(X86_FEATURE_XMM)
 #define cpu_has_ht             boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp             boot_cpu_has(X86_FEATURE_MP)
+#define cpu_has_nx             boot_cpu_has(X86_FEATURE_NX)
 #define cpu_has_k6_mtrr                boot_cpu_has(X86_FEATURE_K6_MTRR)
 #define cpu_has_cyrix_arr      boot_cpu_has(X86_FEATURE_CYRIX_ARR)
 #define cpu_has_centaur_mcr    boot_cpu_has(X86_FEATURE_CENTAUR_MCR)
index 93801084f62f87051c7335e4accec90afb500f8e..9b3c55fb1170d1a5f35a403fb625d200439fe563 100644 (file)
 /* Page-table type. */
 #ifndef __ASSEMBLY__
 typedef struct { unsigned long pt_lo; } pagetable_t;
-#define pagetable_val(_x)  ((_x).pt_lo)
-#define mk_pagetable(_x)   ( (pagetable_t) { (_x) } )
+#define pagetable_val(_x)   ((_x).pt_lo)
+#define mk_pagetable(_x)    ( (pagetable_t) { (_x) } )
 #endif
 
 #ifndef __ASSEMBLY__
-#define PAGE_SIZE               (1UL << PAGE_SHIFT)
+#define PAGE_SIZE           (1UL << PAGE_SHIFT)
 #else
-#define PAGE_SIZE               (1 << PAGE_SHIFT)
+#define PAGE_SIZE           (1 << PAGE_SHIFT)
 #endif
-#define PAGE_MASK               (~(PAGE_SIZE-1))
+#define PAGE_MASK           (~(PAGE_SIZE-1))
 
-#define clear_page(_p)           memset((void *)(_p), 0, PAGE_SIZE)
-#define copy_page(_t,_f)         memcpy((void *)(_t), (void *)(_f), PAGE_SIZE)
+#define clear_page(_p)      memset((void *)(_p), 0, PAGE_SIZE)
+#define copy_page(_t,_f)    memcpy((void *)(_t), (void *)(_f), PAGE_SIZE)
 
-#define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
-#define __pa(x)                        ((unsigned long)(x)-PAGE_OFFSET)
-#define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
-#define pfn_to_page(_pfn)       (frame_table + (_pfn))
-#define phys_to_page(kaddr)     (frame_table + ((kaddr) >> PAGE_SHIFT))
-#define virt_to_page(kaddr)    (frame_table + (__pa(kaddr) >> PAGE_SHIFT))
-#define VALID_PAGE(page)       ((page - frame_table) < max_mapnr)
+#define PAGE_OFFSET         ((unsigned long)__PAGE_OFFSET)
+#define __pa(x)             ((unsigned long)(x)-PAGE_OFFSET)
+#define __va(x)             ((void *)((unsigned long)(x)+PAGE_OFFSET))
+#define pfn_to_page(_pfn)   (frame_table + (_pfn))
+#define phys_to_page(kaddr) (frame_table + ((kaddr) >> PAGE_SHIFT))
+#define virt_to_page(kaddr) (frame_table + (__pa(kaddr) >> PAGE_SHIFT))
+#define VALID_PAGE(page)    ((page - frame_table) < max_mapnr)
 
 /*
  * NB. We don't currently track I/O holes in the physical RAM space.
  * For now we guess that I/O devices will be mapped in the first 1MB
  * (e.g., VGA buffers) or beyond the end of physical RAM.
  */
-#define pfn_is_ram(_pfn)        (((_pfn) > 0x100) && ((_pfn) < max_page))
+#define pfn_is_ram(_pfn)    (((_pfn) > 0x100) && ((_pfn) < max_page))
 
 /* High table entries are reserved by the hypervisor. */
-#define DOMAIN_ENTRIES_PER_L2_PAGETABLE            \
+#define DOMAIN_ENTRIES_PER_L2_PAGETABLE     \
   (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT)
 #define HYPERVISOR_ENTRIES_PER_L2_PAGETABLE \
   (L2_PAGETABLE_ENTRIES - DOMAIN_ENTRIES_PER_L2_PAGETABLE)
@@ -65,48 +65,48 @@ extern void paging_init(void);
 /* Flush global pages as well. */
 
 #define __pge_off()                                                     \
-        do {                                                            \
-                __asm__ __volatile__(                                   \
-                        "mov %0, %%cr4;  # turn off PGE     "           \
-                        :: "r" (mmu_cr4_features & ~X86_CR4_PGE));      \
-        } while (0)
+    do {                                                                \
+        __asm__ __volatile__(                                           \
+            "mov %0, %%cr4;  # turn off PGE     "                       \
+            : : "r" (mmu_cr4_features & ~X86_CR4_PGE) );                \
+        } while ( 0 )
 
 #define __pge_on()                                                      \
-        do {                                                            \
-                __asm__ __volatile__(                                   \
-                        "mov %0, %%cr4;  # turn off PGE     "           \
-                        :: "r" (mmu_cr4_features));                     \
-        } while (0)
+    do {                                                                \
+        __asm__ __volatile__(                                           \
+            "mov %0, %%cr4;  # turn off PGE     "                       \
+            : : "r" (mmu_cr4_features) );                               \
+    } while ( 0 )
 
 
-#define __flush_tlb_pge()                                              \
-       do {                                                            \
-                __pge_off();                                            \
-               __flush_tlb();                                          \
-                __pge_on();                                             \
-       } while (0)
+#define __flush_tlb_pge()                                               \
+    do {                                                                \
+        __pge_off();                                                    \
+        __flush_tlb();                                                  \
+        __pge_on();                                                     \
+    } while ( 0 )
 
 #define __flush_tlb_one(__addr) \
-__asm__ __volatile__("invlpg %0": :"m" (*(char *) (__addr)))
+    __asm__ __volatile__("invlpg %0": :"m" (*(char *) (__addr)))
 
 #endif /* !__ASSEMBLY__ */
 
 
-#define _PAGE_PRESENT  0x001
-#define _PAGE_RW       0x002
-#define _PAGE_USER     0x004
-#define _PAGE_PWT      0x008
-#define _PAGE_PCD      0x010
-#define _PAGE_ACCESSED 0x020
-#define _PAGE_DIRTY    0x040
-#define _PAGE_PAT       0x080
-#define _PAGE_PSE      0x080
-#define _PAGE_GLOBAL   0x100
+#define _PAGE_PRESENT  0x001UL
+#define _PAGE_RW       0x002UL
+#define _PAGE_USER     0x004UL
+#define _PAGE_PWT      0x008UL
+#define _PAGE_PCD      0x010UL
+#define _PAGE_ACCESSED 0x020UL
+#define _PAGE_DIRTY    0x040UL
+#define _PAGE_PAT      0x080UL
+#define _PAGE_PSE      0x080UL
+#define _PAGE_GLOBAL   0x100UL
 
 #define __PAGE_HYPERVISOR \
-       (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+    (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
 #define __PAGE_HYPERVISOR_NOCACHE \
-       (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED)
+    (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED)
 
 #define MAKE_GLOBAL(_x) ((_x) | _PAGE_GLOBAL)
 
index 9b5efe82b87a1546556421488d7b2cc8d57508c9..277888d7ace0375f79a17ba3f3bb15c59ec479f8 100644 (file)
@@ -27,20 +27,24 @@ typedef l2_pgentry_t root_pgentry_t;
 #endif /* !__ASSEMBLY__ */
 
 /* Strip type from a table entry. */
-#define l1_pgentry_val(_x) ((_x).l1_lo)
-#define l2_pgentry_val(_x) ((_x).l2_lo)
+#define l1_pgentry_val(_x)   ((_x).l1_lo)
+#define l2_pgentry_val(_x)   ((_x).l2_lo)
+#define root_pgentry_val(_x) (l2_pgentry_val(_x))
 
 /* Add type to a table entry. */
-#define mk_l1_pgentry(_x)  ( (l1_pgentry_t) { (_x) } )
-#define mk_l2_pgentry(_x)  ( (l2_pgentry_t) { (_x) } )
+#define mk_l1_pgentry(_x)   ( (l1_pgentry_t) { (_x) } )
+#define mk_l2_pgentry(_x)   ( (l2_pgentry_t) { (_x) } )
+#define mk_root_pgentry(_x) (mk_l2_pgentry(_x))
 
 /* Turn a typed table entry into a physical address. */
-#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & PAGE_MASK)
-#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PAGE_MASK)
+#define l1_pgentry_to_phys(_x)   (l1_pgentry_val(_x) & PAGE_MASK)
+#define l2_pgentry_to_phys(_x)   (l2_pgentry_val(_x) & PAGE_MASK)
+#define root_pgentry_to_phys(_x) (l2_pgentry_to_phys(_x))
 
 /* Turn a typed table entry into a page index. */
-#define l1_pgentry_to_pfn(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT) 
-#define l2_pgentry_to_pfn(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT)
+#define l1_pgentry_to_pfn(_x)   (l1_pgentry_val(_x) >> PAGE_SHIFT) 
+#define l2_pgentry_to_pfn(_x)   (l2_pgentry_val(_x) >> PAGE_SHIFT)
+#define root_pgentry_to_pfn(_x) (l2_pgentry_to_pfn(_x))
 
 /* Pagetable walking. */
 #define l2_pgentry_to_l1(_x) \
@@ -55,4 +59,13 @@ typedef l2_pgentry_t root_pgentry_t;
 /* Given a virtual address, get an entry offset into a linear page table. */
 #define l1_linear_offset(_a) ((_a) >> PAGE_SHIFT)
 
+#define PGT_root_page_table PGT_l2_page_table
+
+#define _PAGE_NX         0UL
+
+#define L1_DISALLOW_MASK (3UL << 7)
+#define L2_DISALLOW_MASK (7UL << 7)
+#define L3_DISALLOW_MASK (7UL << 7)
+#define L2_DISALLOW_MASK (7UL << 7)
+
 #endif /* __X86_32_PAGE_H__ */
index 318df434fc94789342bada30da25fc2298aedf10..96bdb540f189278140e6e944a4e88bbd0da50e50 100644 (file)
@@ -18,8 +18,8 @@
 
 #define __PAGE_OFFSET           (0xFFFF830000000000)
 
-/* These may increase in future (phys. bits in particular). */
-#define PADDR_BITS              40
+/* These are page-table limitations. Current CPUs support only 40-bit phys. */
+#define PADDR_BITS              52
 #define VADDR_BITS              48
 #define PADDR_MASK              ((1UL << PADDR_BITS)-1)
 #define VADDR_MASK              ((1UL << VADDR_BITS)-1)
@@ -34,28 +34,32 @@ typedef l4_pgentry_t root_pgentry_t;
 #endif /* !__ASSEMBLY__ */
 
 /* Strip type from a table entry. */
-#define l1_pgentry_val(_x) ((_x).l1_lo)
-#define l2_pgentry_val(_x) ((_x).l2_lo)
-#define l3_pgentry_val(_x) ((_x).l3_lo)
-#define l4_pgentry_val(_x) ((_x).l4_lo)
+#define l1_pgentry_val(_x)   ((_x).l1_lo)
+#define l2_pgentry_val(_x)   ((_x).l2_lo)
+#define l3_pgentry_val(_x)   ((_x).l3_lo)
+#define l4_pgentry_val(_x)   ((_x).l4_lo)
+#define root_pgentry_val(_x) (l4_pgentry_val(_x))
 
 /* Add type to a table entry. */
-#define mk_l1_pgentry(_x)  ( (l1_pgentry_t) { (_x) } )
-#define mk_l2_pgentry(_x)  ( (l2_pgentry_t) { (_x) } )
-#define mk_l3_pgentry(_x)  ( (l3_pgentry_t) { (_x) } )
-#define mk_l4_pgentry(_x)  ( (l4_pgentry_t) { (_x) } )
+#define mk_l1_pgentry(_x)   ( (l1_pgentry_t) { (_x) } )
+#define mk_l2_pgentry(_x)   ( (l2_pgentry_t) { (_x) } )
+#define mk_l3_pgentry(_x)   ( (l3_pgentry_t) { (_x) } )
+#define mk_l4_pgentry(_x)   ( (l4_pgentry_t) { (_x) } )
+#define mk_root_pgentry(_x) (mk_l4_pgentry(_x))
 
 /* Turn a typed table entry into a physical address. */
-#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK))
-#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK))
-#define l3_pgentry_to_phys(_x) (l3_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK))
-#define l4_pgentry_to_phys(_x) (l4_pgentry_val(_x) & (PADDR_MASK & PAGE_MASK))
+#define l1_pgentry_to_phys(_x)   (l1_pgentry_val(_x) & (PADDR_MASK&PAGE_MASK))
+#define l2_pgentry_to_phys(_x)   (l2_pgentry_val(_x) & (PADDR_MASK&PAGE_MASK))
+#define l3_pgentry_to_phys(_x)   (l3_pgentry_val(_x) & (PADDR_MASK&PAGE_MASK))
+#define l4_pgentry_to_phys(_x)   (l4_pgentry_val(_x) & (PADDR_MASK&PAGE_MASK))
+#define root_pgentry_to_phys(_x) (l4_pgentry_to_phys(_x))
 
 /* Turn a typed table entry into a page index. */
-#define l1_pgentry_to_pfn(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT) 
-#define l2_pgentry_to_pfn(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT)
-#define l3_pgentry_to_pfn(_x) (l3_pgentry_val(_x) >> PAGE_SHIFT)
-#define l4_pgentry_to_pfn(_x) (l4_pgentry_val(_x) >> PAGE_SHIFT)
+#define l1_pgentry_to_pfn(_x)   (l1_pgentry_val(_x) >> PAGE_SHIFT) 
+#define l2_pgentry_to_pfn(_x)   (l2_pgentry_val(_x) >> PAGE_SHIFT)
+#define l3_pgentry_to_pfn(_x)   (l3_pgentry_val(_x) >> PAGE_SHIFT)
+#define l4_pgentry_to_pfn(_x)   (l4_pgentry_val(_x) >> PAGE_SHIFT)
+#define root_pgentry_to_pfn(_x) (l4_pgentry_to_pfn(_x))
 
 /* Pagetable walking. */
 #define l2_pgentry_to_l1(_x) \
@@ -78,4 +82,13 @@ typedef l4_pgentry_t root_pgentry_t;
 /* Given a virtual address, get an entry offset into a linear page table. */
 #define l1_linear_offset(_a) (((_a) & VADDR_MASK) >> PAGE_SHIFT)
 
+#define PGT_root_page_table PGT_l4_page_table
+
+#define _PAGE_NX         (cpu_has_nx ? (1UL<<63) : 0UL)
+
+#define L1_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (3UL << 7))
+#define L2_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (7UL << 7))
+#define L3_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (7UL << 7))
+#define L4_DISALLOW_MASK ((cpu_has_nx?0:(1UL<<63)) | (7UL << 7))
+
 #endif /* __X86_64_PAGE_H__ */